/**
 * 
 */
package assignment0.tokenizer;

import java.util.ArrayList;
import java.util.List;

import assignment0.scanner.Scanner;
import assignment0.scanner.ScannerImpl;
import assignment0.tokenizer.Token.Type;

public class TokenizerImpl implements Tokenizer {

	Scanner scanner;
	int counter = -1;
	boolean identifierFound = false;
	List<Token> tokens = new ArrayList<Token>();

	public TokenizerImpl(Scanner sc) {
		this.scanner = sc;
		addAllTokens();
	}

	@Override
	public Token current() {
		return tokens.get(counter);
	}

	@Override
	public Token next() {
		if (counter + 1 < tokens.size()) {
			counter++;
			return tokens.get(counter);
		} else {
			return null;
		}
	}

	@Override
	public Token peek() {
		if (counter + 1 < tokens.size()) {
			return tokens.get(counter + 1);
		}
		{
			return null;
		}
	}

	private void addAllTokens() {
		while (scanner.next() != ScannerImpl.EOF) {
			tokens.add(extractToken());
		}
	}

	private Token extractToken() {
		char character = scanner.current();

		if (Character.isWhitespace(character)) {
			character = scanner.next();
		}

		if (character == ScannerImpl.EOF) {
			return new Token("", "", Type.EOF);
		} else if (Character.isDigit(character)) {
			return extractNumber();
		} else if (Type.OPERATORS.containsKey(String.valueOf(character))) {
			return extractOperator();
		} else if (Character.isLetter(character)) {
			if (identifierFound == false) {
				identifierFound = true;
				return extractIdentifier();
			} else {
				throw new RuntimeException("Invalid character '" + character
						+ "' found!");
			}
		} else {
			throw new RuntimeException("Character " + character
					+ " could not be handled.");
		}
	}

	private Token extractNumber() {
		char current = scanner.current();
		String result = "" + current;

		while (Character.isDigit(scanner.peek())) {
			result = result + scanner.next();
		}

		return new Token(null, Integer.valueOf(result), Type.NUMBER);
	}

	private Token extractOperator() {
		String current = String.valueOf(scanner.current());
		Token result = new Token(current, current, Type.OPERATORS.get(current));
		return result;
	}

	private Token extractIdentifier() {
		char current = scanner.current();
		String result = "" + current;

		while (Character.isLetter(scanner.peek())) {
			result = result + scanner.next();
		}

		return new Token(result, result, Type.IDENTIFIER);
	}

}
